package com.wuwei.elearning.question.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wuwei.elearning.question.domain.*;
import com.wuwei.elearning.question.mapper.UserRelationSubjectMapper;
import com.wuwei.elearning.service.CacheService;
import com.wuwei.elearning.enumPackage.Constant;
import com.wuwei.elearning.exception.ElearningMysqlException;
import com.wuwei.elearning.question.mapper.SubjectMapper;
import com.wuwei.elearning.question.service.SubjectService;
import com.wuwei.elearning.question.vo.SubjectImageVo;
import com.wuwei.elearning.question.vo.SubjectVoForElementUi;
import com.wuwei.elearning.utils.MinioUtil;
import com.wuwei.elearning.utils.result.Result;
import com.wuwei.elearning.utils.token.TokenUtil;
import com.wuwei.elearning.vo.PreviewUrlVo;
import com.wuwei.elearning.vo.SubjectDto;
import com.wuwei.elearning.vo.SubjectVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author wuwei
 * @since 2024-02-01
 */
@RestController
@RequestMapping("/elearning/subject")
@CrossOrigin
public class SubjectController {

    @Resource
    private SubjectMapper subjectMapper;

    @Resource
    private SubjectService subjectService;
    @Autowired
    private UserRelationSubjectMapper userRelationSubjectMapper;

    /**
     * 获取所有R3基础执照考试科目
     * @return
     */
    @GetMapping("getAllR3")
    public Result<List<Subject>> getAll (){
        LambdaQueryWrapper<Subject> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(Subject::getName,"R3");
        List<Subject> subjects = subjectMapper.selectList(wrapper);
        return Result.ok(subjects);
    }

    /**
     * 获取所有subject
     * @return
     */
    @GetMapping("getAllSubject")
    public Result<List<Subject>> getAllSubject (){
        LambdaQueryWrapper<Subject> wrapper = new LambdaQueryWrapper<>();
        List<Subject> subjects = subjectMapper.selectList(wrapper);
        return Result.ok(subjects);
    }


    /**
     * 获取满足vant要求的数据结构
     *    options: [
     *         {
     *           text: '浙江省',
     *           value: '330000',
     *           children: [{ text: '杭州市', value: '330100' }],
     *         },
     *         {
     *           text: '江苏省',
     *           value: '320000',
     *           children: [{ text: '南京市', value: '320100' }],
     *         },
     *       ],
     *
     * @return
     */
    @GetMapping("getTree")
    public Result<List<SubjectVo>> getTree (){
        List<SubjectVo> vos = subjectService.getTree();
        return Result.ok(vos);
    }

    @GetMapping("getAllTree")
    public Result<List<SubjectVo>> getAllTree (){
        List<SubjectVo> vos = subjectService.getAllTree();
        return Result.ok(vos);
    }

    @GetMapping("getAllTreeElementUI")
    public Result<List<SubjectVoForElementUi>> getAllTreeElementUI (){
        List<SubjectVoForElementUi> vos = subjectService.getAllTreeElementUI();
        return Result.ok(vos);
    }


    @GetMapping("getById/{id}")
    public Result<SubjectImageVo> getById (@PathVariable("id") Integer id){
        return Result.ok(subjectService.myGetById(id));
    }

    /**
     * 该请求要返回在有效期内的课程
     * @param id
     * @return
     */
    @GetMapping("getSubjectMapById/{id}")
    public Result<HashMap<String,Object>> getSubjectMapById (@PathVariable("id") Long id){
        HashMap<String,Object> res = subjectService.getSubjectMapById(id);
        String cover = res.get("cover").toString();

        // 处理 word_info
        String wordInfo = (String) res.get("word_info");
        JSONArray jsonArray = JSON.parseArray(wordInfo);
        List<Word> wordList = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            Word word = JSON.parseObject(jsonArray.getJSONObject(i).toJSONString(), Word.class);
            String upload = word.getUrl();
            // 构建Redis键
            String redisKey = Constant.MINIO_PDF + upload;
            // 尝试从Redis获取
            String url = cacheService.getPdf(upload, redisKey);
            word.setUrl(url);
            wordList.add(word);
        }
        // 更新 word_info
        res.put("word_info", JSON.toJSONString(wordList));

        // 处理 ppt_info
        String pptInfo = (String) res.get("ppt_info");
        JSONArray array = JSON.parseArray(pptInfo);
        List<Ppt> pptList = new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            // 注意：这里原来用的是 jsonArray，应该用 array
            Ppt ppt = JSON.parseObject(array.getJSONObject(i).toJSONString(), Ppt.class);
            String upload = ppt.getUrl();
            // 构建Redis键
            String redisKey = Constant.MINIO_PDF + upload;
            // 尝试从Redis获取
            String url = cacheService.getPdf(upload, redisKey);
            ppt.setUrl(url);
            pptList.add(ppt);
        }
        // 更新 ppt_info
        res.put("ppt_info", JSON.toJSONString(pptList));

        List<Video> videoList = new ArrayList<>();
        String videoInfo = (String)res.get("video_info");
        JSONArray array2 = JSON.parseArray(videoInfo);
        for (int i = 0; i < array2.size(); i++) {
            // 注意：这里原来用的是 jsonArray，应该用 array
            Video video = JSON.parseObject(array2.getJSONObject(i).toJSONString(), Video.class);
            String upload = video.getUrl();
            // 构建Redis键
            String redisKey = Constant.MINIO_VIDEO + upload;
            // 尝试从Redis获取
            String url = cacheService.getVideo(upload, redisKey);
            video.setUrl(url);
            videoList.add(video);
        }
        res.put("video_info", JSON.toJSONString(videoList));
        // 处理 cover
        String key = Constant.MINIO_COVER + cover;
        String serviceCover = cacheService.getCover(cover, key);
        res.put("cover", serviceCover);
        return Result.ok(res);
    }

    /**
     * 获取执照课程的叶子节点
     * @return
     */
    @GetMapping("getZhizhaoLeafs")
    public Result<List<Subject>> getZhizhaoLeafs (){
        List<Subject> subjects = subjectService.getZhizhaoLeafs();
        return Result.ok(subjects);
    }

    @GetMapping("getByName/{name}")
    public Result<List<Subject>> getByName (@PathVariable("name") String name){
        LambdaQueryWrapper<Subject> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(name!=null&&!"".equals(name),Subject::getName,name);
        Subject subject = subjectMapper.selectOne(wrapper1);

        LambdaQueryWrapper<Subject> wrapper = new LambdaQueryWrapper<>();
        List<Subject> subjects = new ArrayList<>();
        if (subject!=null) {
            wrapper.eq(Subject::getParentId,subject.getId());
            subjects = subjectMapper.selectList(wrapper);
        }
        return Result.ok(subjects);
    }

    @GetMapping("getLeafs")
    public Result<List<Subject>> getLeafs (){
        List<Subject> subjects = subjectService.getLeafs();
        return Result.ok(subjects);
    }

    @Resource
    private MinioUtil minioUtil;

    @PostMapping("upload/{id}")
    public Result<PreviewUrlVo> file(MultipartFile file, @PathVariable("id") Long id){
        if (file.getSize() != 0) {
            String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
            String upperCase = suffix.toUpperCase();
            String jpg = "jpg".toUpperCase();
            String png = "png".toUpperCase();
            String jpeg = "jpeg".toUpperCase();
            if (!jpg.equals(upperCase)&&!png.equals(upperCase)&&!jpeg.equals(upperCase)) {
                throw new ElearningMysqlException(30044,"请选择jpg、png或jpeg格式的图片！");
            }

            if (file.getSize()!=0) {
                PreviewUrlVo previewUrlVo = subjectService.uploadCover(file, id);
                return Result.ok(previewUrlVo);
            }
            throw new ElearningMysqlException(30044,"上传失败！");
        } else {
            throw new ElearningMysqlException(30044,"您没有上传任何文件");
        }
    }



    @PostMapping("delete/{id}")
    public Result<String> delete(@PathVariable("id") Long id){
        subjectService.myDelete(id);
        return Result.ok("删除成功！");
    }

    @PutMapping("updateService/{onService}/{id}")
    public Result<String> updateService(@PathVariable("onService") Short onService,@PathVariable("id")Long id){
        String res =  subjectService.updateService(onService,id);
        return Result.ok(res);
    }

    @PutMapping("updateNeedTest/{needTest}/{id}")
    public Result<String> updateNeedTest(@PathVariable("needTest") Short needTest,@PathVariable("id")Long id){
        String res =  subjectService.updateNeedTest(needTest,id);
        return Result.ok(res);
    }

    @PostMapping("update")
    public Result<String> update(@RequestBody SubjectDto subject, HttpServletRequest request){
        String token = request.getHeader("Authorization");
        Long account = TokenUtil.getAccountFromToken(token);
        subjectService.myUpdate(account,subject);
        return Result.ok("更新成功!");
    }

    @PostMapping("save")
    public Result<String> save (@RequestBody SubjectDto subjectDto, HttpServletRequest request){
        String token = request.getHeader("Authorization");
        Long account = TokenUtil.getAccountFromToken(token);
        subjectService.mySave(account,subjectDto);
        return Result.ok("添加成功！");
    }


    @GetMapping("getParent")
    public Result< List<Subject>> getParent(){
        LambdaQueryWrapper<Subject> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.isNull(Subject::getParentId);
        List<Subject> subjects = subjectMapper.selectList(queryWrapper);
        return Result.ok(subjects);
    }

    @PostMapping("updateTree")
    public Result<String> updateTree(@RequestBody List<SubjectVoForElementUi> subjectVos, HttpServletRequest request){
        String token = request.getHeader("Authorization");
        Long account = TokenUtil.getAccountFromToken(token);
        subjectService.updateTree(subjectVos,account);
        return Result.ok("更新成功！");
    }

    @Resource
    private CacheService cacheService;


    /**
     * 该请求要返回在有效期时间内的课程
     * @param id
     * @return
     */
    @GetMapping("getByParentId/{id}/{currentPage}/{pageSize}")
    public Result<IPage<Subject>> getByParentId(@PathVariable("id") Long id,
                                               @PathVariable("currentPage") Integer currentPage,
                                               @PathVariable("pageSize") Integer pageSize){
        IPage<Subject> page = new Page<Subject>();
        page.setCurrent(currentPage);
        page.setSize(pageSize);
        LambdaQueryWrapper<Subject> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Subject::getParentId,id)
                .and(w -> w.isNull(Subject::getEndTime).or(i -> i.ge(Subject::getEndTime, LocalDate.now())))
                .eq(Subject::getOnService,1);
        IPage<Subject> subjectIPage = subjectMapper.selectPage(page, wrapper);
        List<Subject> subjects = subjectIPage.getRecords();
        for (Subject subject : subjects) {
            String cover = subject.getCover();
            // 构建Redis键
            String redisKey = Constant.MINIO_COVER + cover;
            // 尝试从Redis获取
            String serviceCover = cacheService.getCover(cover, redisKey);
            subject.setCover(serviceCover);
        }
        subjectIPage.setRecords(subjects);
        return Result.ok(subjectIPage);
    }
}

